package com.auxgroup.smarthome.enterpriseapi;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.auxgroup.smarthome.BeanUtils;
import com.auxgroup.smarthome.enterpriseapi.apiurl.GEApi;
import com.auxgroup.smarthome.enterpriseapi.requestbody.AssociationInfoBody;
import com.auxgroup.smarthome.enterpriseapi.requestbody.BigDataHistoryBody;
import com.auxgroup.smarthome.enterpriseapi.requestbody.BindAndUnbindBody;
import com.auxgroup.smarthome.enterpriseapi.requestbody.DeviceAggDataBody;
import com.auxgroup.smarthome.enterpriseapi.requestbody.DeviceAttrsDataBody;
import com.auxgroup.smarthome.enterpriseapi.requestbody.DeviceCmdBody;
import com.auxgroup.smarthome.enterpriseapi.requestbody.DevicesLocationsBody;
import com.auxgroup.smarthome.enterpriseapi.requestbody.DevicesOnlineDataBody;
import com.auxgroup.smarthome.enterpriseapi.requestbody.GetDeviceActiveDetailBody;
import com.auxgroup.smarthome.enterpriseapi.requestbody.GetTokenBody;
import com.auxgroup.smarthome.enterpriseapi.requestbody.SearchDeviceBtBody;
import com.auxgroup.smarthome.enterpriseapi.requestbody.SearchDeviceWiFiBody;
import com.auxgroup.smarthome.enterpriseapi.requestbody.SearchUserDetailsBody;
import com.auxgroup.smarthome.enterpriseapi.requestbody.UpdateDeviceGroupsBody;
import com.auxgroup.smarthome.enterpriseapi.requestbody.auxrequest.AuxDeviceAggDataBody;
import com.auxgroup.smarthome.enterpriseapi.responsebody.*;
import com.auxgroup.smarthome.enterpriseapi.responsebody.auxresult.AuxAggDataResult;
import com.auxgroup.smarthome.enterpriseapi.responsebody.auxresult.AuxDatapointDetailResult;
import com.auxgroup.smarthome.enterpriseapi.responsebody.auxresult.AuxDeviceErrorDetailResult;
import com.auxgroup.smarthome.enterpriseapi.responsebody.auxresult.AuxDeviceSummaryResult;
import com.auxgroup.smarthome.enterpriseapi.responsebody.auxresult.AuxDeviceTrendResult;
import com.auxgroup.smarthome.enterpriseapi.responsebody.auxresult.AuxUserIncrHistory;
import com.auxgroup.smarthome.enterpriseapi.responsebody.auxresult.AuxUserSummaryResult;
import com.auxgroup.smarthome.enterpriseapi.responsebody.auxresult.AuxUserTotal;
import com.auxgroup.smarthome.enterpriseapi.responsebody.auxresult.AuxUserTrendResult;
import com.auxgroup.smarthome.enterpriseapi.responsebody.auxresult.ExtDatapointResult;
import com.auxgroup.smarthome.utils.HttpClientUtil;

import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Created by kevin chen on 2017/3/5 0005.
 */
public final class EnterpriseApi {

    /**
     * 产品管理
     */
    public static class ProcuctManagement {

        /**
         * POST 获取产品token
         * @return
         */
        public static ProductAccessToken getProductToken(String pk, GetTokenBody getTokenBody){
            String result =  HttpClientUtil.httpRequest(GEApi.GET_PRODUCT_TOKEN.getUrl(pk),null, JSON.toJSONString(getTokenBody), GEApi.GET_PRODUCT_TOKEN.getMethodType());
            return JSON.parseObject(result, ProductAccessToken.class);
        }

        /**
         * 获取产品信息列表
         * @param eid
         * @param esecret
         * @return
         */
        public static ProductList getProductList(String eid, String esecret){
            Map<String,String> headerMap = new HashMap<String,String>();
            headerMap.put("X-Gizwits-Enterprise-ID",eid);
            headerMap.put("X-Gizwits-Enterprise-Secret",esecret);
            String result = HttpClientUtil.httpRequest(GEApi.GET_PRODUCT_LIST.getUrl(), headerMap, "", GEApi.GET_PRODUCT_LIST.getMethodType());
            return JSON.parseObject(result,ProductList.class);
        }

        /**
         * 获取产品信息
         * @return
         */
        public static ProductInfo getProductInfo(String token, String pk){
            String result =  HttpClientUtil.httpRequest(GEApi.GET_PRODUCT_INFO.getUrl(pk), GEApi.getHeaderMap(token), "", GEApi.GET_PRODUCT_INFO.getMethodType());
            return JSON.parseObject(result, ProductInfo.class);
        }

        /**
         * 获取产品数据点
         * @return
         */
        public static JSONObject getProductPoint(String token,String pk){
            String result =  HttpClientUtil.httpRequest(String.format(GEApi.GET_PRODUCT_DATA_POINT.getUrl(), pk), GEApi.getHeaderMap(token), "", GEApi.GET_PRODUCT_DATA_POINT.getMethodType());
            return JSONObject.parseObject(result);
        }

        /**
         * 关联产品
         * @param pk
         * @param body
         * @return JSONObject
         */
        public static JSONObject associationProduct(String pk,AssociationInfoBody body){
            String result = HttpClientUtil.httpRequest(GEApi.ASSOCIATION_PKS.getUrl(pk),null,JSON.toJSONString(body), GEApi.ASSOCIATION_PKS.getMethodType());
            return JSON.parseObject(result);
        }

    }


    /**
     * 内部管理
     */
    public static class  InternalManagement {
        /**
         * GET 获取企业关联的产品列表
         * @return
         */
        public static ProductInfo getProductMessage(String token, String eid, String limit, String skip){
            String result =  HttpClientUtil.httpRequest(GEApi.ASSOCIATIONS_PRODUCT_LIST.getUrl(eid,limit,skip), GEApi.getHeaderMap(token),"", GEApi.ASSOCIATIONS_PRODUCT_LIST.getMethodType());
            return JSON.parseObject(result, ProductInfo.class);
        }

    }


    /**
     * 设备报表
     */
    public static class DeviceReport {
        /**
         * 获取设备实时激活报表
         * 返回的response是动态的  所以根据具体的对象来解析
         */
        public static RealtimeReportReponse getDeviceRealtimeReport(String token , String pk, String gid){
            String result =  HttpClientUtil.httpRequest(GEApi.GET_REPORT_RT.getUrl(pk, gid),
                    GEApi.getHeaderMap(token), "", GEApi.GET_REPORT_RT.getMethodType());
            return JSONObject.parseObject(result, RealtimeReportReponse.class);
        }

        /**
         * 获取设备激活报表
         */
        public static DeviceActivationReportBody getDeviceActivationReport(String token , String pk, String gid){
            String result =  HttpClientUtil.httpRequest(GEApi.GET_REPORT_ACTIVATION.getUrl(pk, gid),
                    GEApi.getHeaderMap(token), "", GEApi.GET_REPORT_ACTIVATION.getMethodType());
            return JSONObject.parseObject(result, DeviceActivationReportBody.class);
        }

        /**
         * 获取激活历史报表（大数据）
         * @param token
         * @param pk
         * @param body
         * @return
         */
        public static ActivationHistoryReport getActivationHistoryReport(String token, String pk, BigDataHistoryBody body){
            String result =  HttpClientUtil.httpRequest(GEApi.GET_REPORT_ACTIVATION_HISTORY.getUrl(pk, BeanUtils.getRequestUrlPath(body)),
                    GEApi.getHeaderMap(token), "", GEApi.GET_REPORT_ACTIVATION_HISTORY.getMethodType());

            return JSONObject.parseObject(result,ActivationHistoryReport.class);
        }

        /**
         * 获取活跃设备报表
         * @param token
         * @param pk
         * @param gid
         */
        public static DeviceLivenessReportReponse getDeviceLivenessReport(String token, String pk, String gid) {
            String result =  HttpClientUtil.httpRequest(GEApi.GET_REPORT_LIVENESS.getUrl(pk, gid),
                    GEApi.getHeaderMap(token), "", GEApi.GET_REPORT_LIVENESS.getMethodType());
            return JSONObject.parseObject(result, DeviceLivenessReportReponse.class);
        }

        /**
         * 获取活跃历史报表（大数据）
         * @param token
         * @param pk
         * @param body
         * @return
         */
        public static LivenessHistoryReport getLivenessHistoryReport(String token, String pk, BigDataHistoryBody body){
            String result =  HttpClientUtil.httpRequest(GEApi.GET_REPORT_LIVENESS_HISTORY.getUrl(pk, BeanUtils.getRequestUrlPath(body)),
                    GEApi.getHeaderMap(token), "", GEApi.GET_REPORT_LIVENESS_HISTORY.getMethodType());
            return JSONObject.parseObject(result,LivenessHistoryReport.class);
        }

        /**
         * 获取活跃设备报表
         * 返回的值是动态属性，手动解析
         */
        public static DeviceLivenessReportReponse getDeviceLivenessDeviceReport(String token , String pk, String gid){
            String result =  HttpClientUtil.httpRequest(GEApi.GET_REPORT_LIVENESS.getUrl(pk, gid),
                    GEApi.getHeaderMap(token), "", GEApi.GET_REPORT_LIVENESS.getMethodType());
            return JSONObject.parseObject(result, DeviceLivenessReportReponse.class);
        }

        /**
         * 设备概览
         */
        public static DeviceSurvey getDeviceSummary(String token , String pk){
            String result =  HttpClientUtil.httpRequest(GEApi.GET_REPORT_DEVICE_SUMMARY.getUrl(pk),
                    GEApi.getHeaderMap(token), "", GEApi.GET_REPORT_DEVICE_SUMMARY.getMethodType());

            return JSONObject.parseObject(result,DeviceSurvey.class);
        }


        /**
         * 设备活跃详情
         */
        public static DeviceActiveDetails getDeviceActiveDetail(String token , String pk, GetDeviceActiveDetailBody body){
            String result =  HttpClientUtil.httpRequest(GEApi.GET_REPORT_DEVICE_ACTIVE_DETAIL.getUrl(pk,body.getStart(),body.getEnd(),body.getCountry(),body.getRegion(),body.getCity()),
                    GEApi.getHeaderMap(token), "", GEApi.GET_REPORT_DEVICE_ACTIVE_DETAIL.getMethodType());
            return JSONObject.parseObject(result,DeviceActiveDetails.class);
        }

        /**
         * 设备新增详情
         */
        public static DeviceNewAddDetails getDeviceNewAddReport(String token , String pk, GetDeviceActiveDetailBody body){
            String result =  HttpClientUtil.httpRequest(GEApi.GET_REPORT_DEVICE_NEW_ADD_DETAIL.getUrl(pk,body.getStart(),body.getEnd(),body.getCountry(),body.getRegion(),body.getCity()),
                    GEApi.getHeaderMap(token), "", GEApi.GET_REPORT_DEVICE_NEW_ADD_DETAIL.getMethodType());

            return JSONObject.parseObject(result,DeviceNewAddDetails.class);
        }

        /**
         * 产品活跃周期查询
         * @param token
         * @param pk
         * @return
         */
        public static ActiveCycle getActiveCycleReport(String token, String pk) {
            String result =  HttpClientUtil.httpRequest(GEApi.GET_REPORT_AVICE_CYCLE.getUrl(pk), GEApi.getHeaderMap(token),  "", GEApi.GET_REPORT_AVICE_CYCLE.getMethodType());
            return JSONObject.parseObject(result, ActiveCycle.class);
        }

        /**
         *  连接时长查询报表
         * @param token
         * @param pk
         * @return
         */
        public static ConnectionDurationResponse getConnectionDurationReport(String token, String pk) {
            String result =  HttpClientUtil.httpRequest(GEApi.CONNECTION_DURATION.getUrl(pk), GEApi.getHeaderMap(token),  "", GEApi.CONNECTION_DURATION.getMethodType());
            return JSONObject.parseObject(result, ConnectionDurationResponse.class);
        }

        /**
         * 获取故障设备台数报表
         * 返回的值是动态属性，手动解析
         */
        public static FaultAndAlertQuantityReportResponse getDeviceFaultReport(String token , String pk, String gid){
            String result =  HttpClientUtil.httpRequest(GEApi.GET_REPORT_FAULT_DEVICE.getUrl(pk, gid),
                    GEApi.getHeaderMap(token), "", GEApi.GET_REPORT_FAULT_DEVICE.getMethodType());
            return JSONObject.parseObject(result, FaultAndAlertQuantityReportResponse.class);
        }

        /**
         * 获取报警设备台数报表
         * 返回的值是动态属性，手动解析
         */
        public static FaultAndAlertQuantityReportResponse getDeviceAlertReport(String token , String pk, String gid){
            String result =  HttpClientUtil.httpRequest(GEApi.GET_REPORT_ALERT_DEVICE.getUrl(pk, gid),
                    GEApi.getHeaderMap(token), "", GEApi.GET_REPORT_ALERT_DEVICE.getMethodType());
            return JSONObject.parseObject(result, FaultAndAlertQuantityReportResponse.class);
        }

        /**
         * 获取故障次数报表
         * 返回的值是动态属性，手动解析
         */
        public static FaultAndAlertEventReportResponse getDeviceFaultFrequency(String token , String pk, String gid){
            String result =  HttpClientUtil.httpRequest(GEApi.GET_REPORT_FAULT_FREQUENCY.getUrl(pk, gid),
                    GEApi.getHeaderMap(token), "", GEApi.GET_REPORT_FAULT_FREQUENCY.getMethodType());
            return JSONObject.parseObject(result, FaultAndAlertEventReportResponse.class);
        }

        /**
         * Not Implemented
         * 获取报警次数报表
         * 返回的值是动态属性，手动解析
         */
        @Deprecated
        public static FaultAndAlertEventReportResponse getDeviceAlertFrequency(String token , String pk, String gid){
            String result =  HttpClientUtil.httpRequest(GEApi.GET_REPORT_ALERT_FREQUENCY.getUrl(pk, gid),
                    GEApi.getHeaderMap(token), "", GEApi.GET_REPORT_ALERT_FREQUENCY.getMethodType());
            return JSONObject.parseObject(result, FaultAndAlertEventReportResponse.class);
        }

        /**
         * 获取自定义事件历史报表
         */
        public static DeviceHistoryDetails getDeviceCustomHistory(String token , String pk, String gid, String cycle, String start, String end){
            String result =  HttpClientUtil.httpRequest(String.format(GEApi.GET_REPORT_CUSTOM_HISTORY.getUrl(),pk,gid,cycle,start,end),
                    GEApi.getHeaderMap(token), "", GEApi.GET_REPORT_CUSTOM_HISTORY.getMethodType());
            return JSONObject.parseObject(result,DeviceHistoryDetails.class);
        }

    }


    public static class DeviceManage {

        /**
         * 获取设备组树形结构
         * @param pk
         * @return
         */
        public static JSONObject getDeviceGroups(String pk) {
            return null;
        }

        /**
         * 创建设备组
         * parent 为可选参数，如果有 parent 表示创建一个子设备组。
         一个产品只能有一个根设备组。
         * @param pk
         * @param parentGid
         * @return
         */
        public static JSONObject createDeviceGroups(String pk, String parentGid) {
            return null;
        }

        /**
         * 删除设备组需要先清空设备组下所有设备及子设备组。
         * @param pk
         * @param gid
         * @return
         */
        public static JSONObject deleteDeviceGroups(String pk, String gid) {
            return null;
        }

        /**
         * 获取设备组下的 MAC 列表（Not Implemented）
         * @param pk
         * @param gid
         * @return
         */
        public static JSONObject getDeviceGroupByGid(String pk, String gid) {
            return null;
        }

        /**
         * 更新设备组
         * 更新设备组
         action: 操作，"assign" | "unassign"
         macs: MAC 列表，最多一次上传 1000 个 MAC
         reassign: 当 action 为 "assign" 时有效。当 reassgin 为 true，MAC 如果已经在某个设备组下面，会被移动到当前组；当 reassign 为 false，MAC 如果已经在某个设备组下面，则移动失败。
         * @param pk
         * @param gid
         * @param updateDeviceGroupsBody
         * @return
         */
        public static JSONObject updateDeviceGroupByGid(String pk, String gid, UpdateDeviceGroupsBody updateDeviceGroupsBody) {
            return null;
        }

        /**
         * 获取设备信息
         * @return
         */
        public static DeviceMessage getDeviceMessage(String token, String pk, String mac){
            String result =  HttpClientUtil.httpRequest(String.format(GEApi.GET_DEVICE_MESSAGE.getUrl(),pk,mac), GEApi.getHeaderMap(token), "", GEApi.GET_DEVICE_MESSAGE.getMethodType());
            return JSONObject.parseObject(result,DeviceMessage.class);
        }

        /**
         * 获取设备详情
         * @return
         */
        public static DeviceDetails getDeviceDetails(String token , String pk, String mac){
            String result =  HttpClientUtil.httpRequest(GEApi.GET_DEVICE_DETAIL.getUrl(pk, mac), GEApi.getHeaderMap(token), "", GEApi.GET_DEVICE_DETAIL.getMethodType());
            return JSONObject.parseObject(result,DeviceDetails.class);
        }

        /**
         * 搜索wifi设备(实时)
         */
        public static WIFIDeviceList searchWiFiDevice(String token , String pk, SearchDeviceWiFiBody body){
            String result =  HttpClientUtil.httpRequest(GEApi.SEARCH_DEVICE.getUrl(pk, BeanUtils.getRequestUrlPath(body)),
                    GEApi.getHeaderMap(token), "", GEApi.SEARCH_DEVICE.getMethodType());
            return JSONObject.parseObject(result,WIFIDeviceList.class);
        }

        /**
         * 搜索蓝牙设备（实时)
         */
        public static BTDeviceList searchBtDevice(String token , String pk, SearchDeviceBtBody body){
            String result =  HttpClientUtil.httpRequest(GEApi.SEARCH_DEVICE_BT.getUrl(pk, BeanUtils.getRequestUrlPath(body)),
                    GEApi.getHeaderMap(token), "", GEApi.SEARCH_DEVICE_BT.getMethodType());
            return JSONObject.parseObject(result,BTDeviceList.class);
        }

        /**
         * 获取设备历史数据 根据日期
         * 返回值得属性是动态  得根据具体产品来配合使用
         * start_ts 和 end_ts不填，默认查询过去到现在两天以内的通信日志记录
         * start_ts与end_ts之间的间隔秒必须在两天范围以内
         * 增加sort排序，默认为降序，asc代表升序，desc代表降序
         * @return
         */
        public static DeviceAttrsData getDeviceHistoryData(String token , String pk, String did, DeviceAttrsDataBody body){
            String result =  HttpClientUtil.httpRequest(GEApi.GET_DEVICE_HISTORY_DATA.getUrl(pk,did, BeanUtils.getRequestUrlPath(body)),
                    GEApi.getHeaderMap(token), "", GEApi.GET_DEVICE_HISTORY_DATA.getMethodType());
            return JSONObject.parseObject(result,DeviceAttrsData.class);
        }

        /**
         * 获取设备上下线记录
         * @return
         */

        public static DeviceOnoffline getDeviceOnofflineData(String token, String pk, String did, DevicesOnlineDataBody body){
            String result =  HttpClientUtil.httpRequest(GEApi.GET_DEVICE_ONOFFLINE_DETAIL.getUrl(pk,did, BeanUtils.getRequestUrlPath(body)),
                    GEApi.getHeaderMap(token), "", GEApi.GET_DEVICE_ONOFFLINE_DETAIL.getMethodType());
            return JSONObject.parseObject(result,DeviceOnoffline.class);
        }

        /**
         * 设备通信日志（实时）
         按 ts 降序排序。
         payload 为二进制进行 base64 编码后的结果。
         * @param token
         * @param pk
         * @param did
         * @param deviceCmdBody
         * @return
         */
        public static DeviceCmd getDeviceCmd(String token, String pk, String did, DeviceCmdBody deviceCmdBody) {
            String result =  HttpClientUtil.httpRequest(GEApi.GET_DEVICE_ONOFFLINE_DETAIL.getUrl(pk,did, BeanUtils.getRequestUrlPath(deviceCmdBody)),
                    GEApi.getHeaderMap(token), "", GEApi.GET_DEVICE_ONOFFLINE_DETAIL.getMethodType());
            return null;
        }

        /**
         * 获取设备地理位置分布
         * gid 默认是不存在的 添加了分组才会有gid
         * 并且地址是动态的，属性无法确定
         * @return
         */
        public static DevicesLocations getDeviceLocation(String token , String pk, DevicesLocationsBody locationsBody){
            String result =  HttpClientUtil.httpRequest(GEApi.GET_DEVICE_LOCATION.getUrl(pk, BeanUtils.getRequestUrlPath(locationsBody)),
                    GEApi.getHeaderMap(token), "", GEApi.GET_DEVICE_LOCATION.getMethodType());
            return JSONObject.parseObject(result,DevicesLocations.class);
        }

        /**
         * 获取蓝牙设备地理位置分布
         * gid 默认是不存在的 添加了分组才会有gid
         * 并且地址是动态的，属性无法确定
         * @return
         */
        public static DevicesLocations getDeviceBtLocation(String token , String pk, DevicesLocationsBody locationsBody){
            String result =  HttpClientUtil.httpRequest(GEApi.GET_DEVICE_BT_LOCATION.getUrl(pk, BeanUtils.getRequestUrlPath(locationsBody)),
                    GEApi.getHeaderMap(token), "", GEApi.GET_DEVICE_BT_LOCATION.getMethodType());
            return JSONObject.parseObject(result,DevicesLocations.class);
        }

        /**
         * 蓝牙设备最近地理位置（实时）
         * @param pk
         * @param deviceSn
         * @return
         */
        public static JSONObject getDeviceBtLastLocation(String pk, String deviceSn) {
            return null;
        }

        /**
         *  解绑设备
         * @param token
         * @param pk
         * @param body
         * @return
         */
        public static BindAndUnbindStatus unbindDevices(String token, String pk, BindAndUnbindBody body){
            String result = HttpClientUtil.httpRequest(GEApi.UNBINDING_DEVICE.getUrl(pk), GEApi.getHeaderMap(token), JSON.toJSONString(body), GEApi.UNBINDING_DEVICE.getMethodType());
            return JSONObject.parseObject(result,BindAndUnbindStatus.class);
        }

        /**
         *  绑定设备
         * @param token
         * @param pk
         * @param body
         * @return
         */
        public static BindAndUnbindStatus bindDevices(String token, String pk, BindAndUnbindBody body){
            String result = HttpClientUtil.httpRequest(GEApi.BINDING_DEVICE.getUrl(pk), GEApi.getHeaderMap(token), JSON.toJSONString(body), GEApi.BINDING_DEVICE.getMethodType());
            return JSONObject.parseObject(result,BindAndUnbindStatus.class);
        }

        /**
         * 控制设备 动态属性 继承RemoteDeviceBody
         * @return
         */
        public static JSONObject controlRemoteDevice(String token ,String pk,String did, String body){
            String result =  HttpClientUtil.httpRequest(GEApi.CONTROL_REMOTE_DEVICE.getUrl(pk,did), GEApi.getHeaderMap(token), body, GEApi.CONTROL_REMOTE_DEVICE.getMethodType());
            return JSONObject.parseObject(result);
        }

        /**
         * 获取中控设备的子设备设备列表
         * @param token
         * @param pk
         * @param did
         * @param limit
         * @param skip
         * @return
         */
        public static ControlSlave getControlSlaveList(String token, String pk, String did, String limit, String skip) {
            String result =  HttpClientUtil.httpRequest(GEApi.GET_CONTROL_SLAVE.getUrl(pk,did, limit, skip), GEApi.getHeaderMap(token), "", GEApi.GET_CONTROL_SLAVE.getMethodType());
            return JSONObject.parseObject(result, ControlSlave.class);
        }


    }


    /**
     * 用户报表
     */
    public static class UserReport {

        /**
         * 用户新增报表
         * 返回的值是动态属性，手动解析
         */
        public static UserNewaddReport getUserNewAdd(String token , String pk, BigDataHistoryBody body){
            String result =  HttpClientUtil.httpRequest(GEApi.GET_USER_REPORT_NEW_ADD.getUrl(pk, BeanUtils.getRequestUrlPath(body)),
                    GEApi.getHeaderMap(token), "", GEApi.GET_USER_REPORT_NEW_ADD.getMethodType());

            return JSONObject.parseObject(result,UserNewaddReport.class);
        }


        /**
         * 用户总数报表
         * 返回的值是动态属性，手动解析 返回参数会有location这个字段
         */
        public static UserTotalDetails getUserTotal(String token , String pk, String ... gid){
            String result =  HttpClientUtil.httpRequest(String.format(GEApi.GET_USER_REPORT_TOTAL.getUrl(), pk, gid),
                    GEApi.getHeaderMap(token), "", GEApi.GET_USER_REPORT_TOTAL.getMethodType());
            return JSONObject.parseObject(result,UserTotalDetails.class);
        }


        /**
         * 蓝牙用户活跃报表
         * 返回的值是动态属性，手动解析
         */
        public static String getLivenessBtUser(String token ,String pk,String gid,String cycle,String start,String end){
            String result =  HttpClientUtil.httpRequest(String.format(GEApi.GET_USER_REPORT_ACTIVE_BT.getUrl(),pk,gid,cycle,start,end),
                    GEApi.getHeaderMap(token), "", GEApi.GET_USER_REPORT_ACTIVE_BT.getMethodType());
            return result;
        }

    }

    public static class UserManagement {
        /**
         * 搜索用户
         */
        public static UserDetails searchUser(String token , String pk, SearchUserDetailsBody body){
            String result =  HttpClientUtil.httpRequest(GEApi.SEARCH_USER.getUrl(pk, BeanUtils.getRequestUrlPath(body)),
                    GEApi.getHeaderMap(token), "", GEApi.SEARCH_USER.getMethodType());
            return JSONObject.parseObject(result,UserDetails.class);
        }
    }


    /**
     * wifi聚合数据
     */
    public static AggDataResult wifiDeviceAggData(String token,String pk,String did,DeviceAggDataBody body){
        String result = HttpClientUtil.httpRequest(GEApi.GET_WIFI_AGG_DATA.getUrl(pk,did, BeanUtils.getRequestUrlPath(body)), GEApi.getHeaderMap(token),"", GEApi.GET_WIFI_AGG_DATA.getMethodType());
        return JSONObject.parseObject(result,AggDataResult.class);
    }


    /**
     * 获取设备地理位置分布(中国省份)
     * gid 默认是不存在的 添加了分组才会有gid
     * 并且地址是动态的，属性无法确定
     * {"total": 10, "gid": null,
     * "location": {"Unknown": {"count": 1, "Unknown": {"count": 1, "Unknown": 1}},
     * "China": {"count": 9, "Guangdong": {"count": 9, "Shenzhen": 9}}}}
     *
     * @return
     */
    public static JSONObject getDeviceLocationChinaPronvice(String token, String pk, DevicesLocationsBody locationsBody){
        String result =  HttpClientUtil.httpRequest(GEApi.GET_DEVICE_LOCATION.getUrl(pk, BeanUtils.getRequestUrlPath(locationsBody)),
                GEApi.getHeaderMap(token), "", GEApi.GET_DEVICE_LOCATION.getMethodType());
        JSONObject resultJson = JSONObject.parseObject(result);
        JSONObject chinaJson = resultJson.getJSONObject("location").getJSONObject("China");
        Set<String> keySet = chinaJson.keySet();
        Integer sum = 0;
        for (String key : keySet) {
            if ("count".equals(key)) {
                sum = chinaJson.getInteger("count");
            }
        }
        for (String key : keySet) {
            if (!"count".equals(key)) {
                JSONObject pronvince = chinaJson.getJSONObject(key);
                Integer count = pronvince.getInteger("count");
                Double percent = count * 100.0 / sum;
                pronvince.put("percent", percent);
            }
        }
        String json = JSONObject.toJSONString(chinaJson, SerializerFeature.SortField);
        Arrays.sort(new JSONObject[]{chinaJson}, new Comparator<JSONObject>() {

            @Override
            public int compare(JSONObject o1, JSONObject o2) {
                return 0;
            }
        });
        return JSON.parseObject(json);
    }

    public static class Aux {

        /**
         * 设备概览
         * @param token
         * @param deviceModel 设备型号, 选填
         * @return
         */
        public static AuxDeviceSummaryResult auxDeviceSummary(String token, String deviceModel){
            String result = HttpClientUtil.httpRequest(GEApi.AUX_DEVICE_SUMMARY.getUrl(deviceModel), GEApi.getHeaderMap(token),"", GEApi.AUX_DEVICE_SUMMARY.getMethodType());
            return JSONObject.parseObject(result,AuxDeviceSummaryResult.class);
        }

        /**
         * 设备趋势
         * @param token
         * @param start  格式：yyyy-MM-dd
         * @param end 格式：yyyy-MM-dd
         * @param deviceModel  设备型号选填
         * @return
         */
        public static AuxDeviceTrendResult auxDeviceTrend(String token, String start, String end, String deviceModel){
            String result = HttpClientUtil.httpRequest(GEApi.AUX_DEVICE_TREND.getUrl(start, end, deviceModel), GEApi.getHeaderMap(token),"", GEApi.AUX_DEVICE_TREND.getMethodType());
            return JSONObject.parseObject(result,AuxDeviceTrendResult.class);
        }

        /**
         * 设备功能使用情况
         * @param token
         * @param deviceModel 设备型号，选填
         * @return
         */
        public static AuxDatapointDetailResult auxDatapointDetail(String token, String deviceModel){
            String result = HttpClientUtil.httpRequest(GEApi.AUX_DATAPOINT_DETAIL.getUrl(deviceModel), GEApi.getHeaderMap(token),"", GEApi.AUX_DATAPOINT_DETAIL.getMethodType());
            return JSONObject.parseObject(result,AuxDatapointDetailResult.class);
        }

        /**
         * 设备分布情况
         * @param token
         * @param type 设备类型：device/fault  必填
         * @param deviceModel 设备型号，选填
         * @return
         */
        public static JSONObject auxDeviceDistribution(String token, String type, String deviceModel){
            String result = HttpClientUtil.httpRequest(GEApi.AUX_DEVICE_DISTRIBUTION.getUrl(type, deviceModel), GEApi.getHeaderMap(token),"", GEApi.AUX_DEVICE_DISTRIBUTION.getMethodType());
            return JSONObject.parseObject(result);
        }

        /**
         * 故障分析情况
         * @param token
         * @param deviceModel 设备型号，选填
         * @return
         */
        public static AuxDeviceErrorDetailResult auxDeviceErrorDetail(String token, String deviceModel){
            String result = HttpClientUtil.httpRequest(GEApi.AUX_DEVICE_ERROR_DETAIL.getUrl(deviceModel), GEApi.getHeaderMap(token),"", GEApi.AUX_DEVICE_ERROR_DETAIL.getMethodType());
            return JSONObject.parseObject(result,AuxDeviceErrorDetailResult.class);
        }

        /**
         * 用户概览
         * @param token
         * @param deviceModel 设备型号，选填
         * @return
         */
        public static AuxUserSummaryResult auxUserSummary(String token, String deviceModel){
            String result = HttpClientUtil.httpRequest(GEApi.AUX_USER_SUMMARY.getUrl(deviceModel), GEApi.getHeaderMap(token),"", GEApi.AUX_USER_SUMMARY.getMethodType());
            return JSONObject.parseObject(result,AuxUserSummaryResult.class);
        }

        /**
         * 用户趋势
         * @param token
         * @param start 开始时间，格式：yyyy-MM-dd
         * @param end 结束时间，格式：yyyy-MM-dd
         * @param deviceModel 设备型号，选填
         * @return
         */
        public static AuxUserTrendResult auxUserTrend(String token, String start, String end, String deviceModel){
            String result = HttpClientUtil.httpRequest(GEApi.AUX_USER_TREND.getUrl(start, end, deviceModel), GEApi.getHeaderMap(token),"", GEApi.AUX_USER_TREND.getMethodType());
            return JSONObject.parseObject(result, AuxUserTrendResult.class);
        }

        /**
         * 用户数量分布情况
         * @param token
         * @param deviceModel
         * @return
         */
        public static JSONObject auxUserDistribution(String token, String deviceModel){
            String result = HttpClientUtil.httpRequest(GEApi.AUX_USER_DISTRIBUTION.getUrl(deviceModel), GEApi.getHeaderMap(token),"", GEApi.AUX_USER_DISTRIBUTION.getMethodType());
            return JSONObject.parseObject(result);
        }

        /**
         * 用户增长历史
         * @param token
         * @param startDate yyyy-MM-dd
         * @param endDate  yyyy-MM-dd
         * @return
         */
        public static List<AuxUserIncrHistory> auxUserIncreaseHistory(String token, String startDate, String endDate){
            String result = HttpClientUtil.httpRequest(GEApi.AUX_USER_INCREASE_HISTORY.getUrl(startDate, endDate), GEApi.getHeaderMap(token),"", GEApi.AUX_USER_INCREASE_HISTORY.getMethodType());
            return JSONObject.parseObject(result, new TypeReference<List<AuxUserIncrHistory>>(){});
        }

        /**
         * 获取用户地理位置人数统计
         * @param token
         * @return
         */
        public static JSONObject auxUserLocationDistribution(String token){
            String result = HttpClientUtil.httpRequest(GEApi.AUX_USER_LOCATION_DISTRIBUTION.getUrl(), GEApi.getHeaderMap(token),"", GEApi.AUX_USER_LOCATION_DISTRIBUTION.getMethodType());
            return JSONObject.parseObject(result);
        }

        /**
         * 获取用户总数
         * @param token
         * @return
         */
        public static AuxUserTotal auxUserTotal(String token){
            String result = HttpClientUtil.httpRequest(GEApi.AUX_USER_TOTAL.getUrl(), GEApi.getHeaderMap(token),"", GEApi.AUX_USER_TOTAL.getMethodType());
            return JSONObject.parseObject(result, AuxUserTotal.class);
        }

        /**
         * 获取wifi设备聚合数据
         * @param token
         * @param pk
         * @param did
         * @param body
         * @return
         */
        public static AuxAggDataResult wifiDeviceAggData(String token, String pk, String did, AuxDeviceAggDataBody body){
            String result = HttpClientUtil.httpRequest(GEApi.AUX_AGG_DATA.getUrl(pk,did, BeanUtils.getRequestUrlPath(body)), GEApi.getHeaderMap(token),"", GEApi.AUX_AGG_DATA.getMethodType());
            return JSONObject.parseObject(result,AuxAggDataResult.class);
        }

        public static JSONObject getLatestDataByCmdAndSrc(String token, String pk, String did, String cmd, String src){
            String result = HttpClientUtil.httpRequest(GEApi.LATEST_DATA_BY_CMD_SRC.getUrl(pk,did, cmd, src), GEApi.getHeaderMap(token),"", GEApi.LATEST_DATA_BY_CMD_SRC.getMethodType());
            return JSONObject.parseObject(result);
        }

        /**
         * 获取透传数据点
         * @param token
         * @param pk
         * @return
         */
        public static List<ExtDatapointResult> getExtDatapoint(String token, String pk){
            String result = HttpClientUtil.httpRequest(GEApi.EXT_DATAPOINT.getUrl(pk), GEApi.getHeaderMap(token),"", GEApi.EXT_DATAPOINT.getMethodType());
            return JSON.parseArray(result, ExtDatapointResult.class);
        }

    }

}
